package com.ssy.lingxi.order.serviceimpl.base;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.manage.ShopTypeEnum;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.order.*;
import com.ssy.lingxi.common.language.LanguageHolder;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.api.model.request.GiftCouponItemRequest;
import com.ssy.lingxi.marketing.api.model.request.GiftCouponRequest;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.order.entity.OrderCouponDO;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.entity.OrderGiveCouponDO;
import com.ssy.lingxi.order.entity.PlatformPaymentParameterDO;
import com.ssy.lingxi.order.model.bo.*;
import com.ssy.lingxi.order.model.constant.*;
import com.ssy.lingxi.order.model.dto.*;
import com.ssy.lingxi.order.model.vo.basic.request.BusinessOrderProductVO;
import com.ssy.lingxi.order.model.vo.basic.request.MobileOrderProductVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderProductVO;
import com.ssy.lingxi.order.model.vo.basic.request.PurchaseOrderProductVO;
import com.ssy.lingxi.order.model.vo.basic.response.DropdownItem;
import com.ssy.lingxi.order.model.vo.buyer.response.BuyerOrderDetailVO;
import com.ssy.lingxi.order.model.vo.platform.response.PlatformOrderDetailVO;
import com.ssy.lingxi.order.model.vo.vendor.response.VendorOrderDetailVO;
import com.ssy.lingxi.order.repository.OrderRepository;
import com.ssy.lingxi.order.repository.PlatformPaymentParameterRepository;
import com.ssy.lingxi.order.service.base.*;
import com.ssy.lingxi.order.service.feign.*;
import com.ssy.lingxi.order.utils.NumberUtil;
import com.ssy.lingxi.order.utils.QRCodeUtil;
import com.ssy.lingxi.product.api.model.request.price.MaterielPriceRequest;
import com.ssy.lingxi.product.api.model.request.price.OrderPriceRequest;
import me.chanjar.weixin.common.error.WxErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 基础订单服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-07-15
 */
@Service
public class BaseOrderServiceImpl implements IBaseOrderService {
    private final static Logger logger = LoggerFactory.getLogger(BaseOrderServiceImpl.class);

    @Resource
    private IBaseOrderProductService baseOrderProductService;

    @Resource
    private IBaseOrderPaymentService baseOrderPaymentService;

    @Resource
    private IBaseOrderConsigneeService baseOrderConsigneeService;

    @Resource
    private IBaseOrderContractService baseOrderContractService;

    @Resource
    private IBaseOrderInvoiceService baseOrderInvoiceService;

    @Resource
    private IBaseOrderRequirementService baseOrderRequirementService;

    @Resource
    private IBaseOrderDeliveryService baseOrderDeliveryService;

    @Resource
    private IBaseOrderHistoryService baseOrderHistoryService;

    @Resource
    private IBaseOrderTaskService baseOrderTaskService;

    @Resource
    private IMemberFeignService memberFeignService;

    @Resource
    private IReportFeignService reportFeignService;

    @Resource
    private IMessageFeignService messageFeignService;

    @Resource
    private IProductFeignService productFeignService;

    @Resource
    private ISearchFeignService searchFeignService;

    @Resource
    private IContractFeignService contractFeignService;

    @Resource
    private ISettleAccountFeignService settleAccountFeignService;

    @Resource
    private IPlatformTemplateFeignService platformTemplateFeignService;

    @Resource
    private IMarketingFeignService marketingFeignService;

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private IBaseOrderService baseOrderService;

    @Resource
    private IBaseOrderScheduleService baseOrderScheduleService;

    @Resource
    private PlatformPaymentParameterRepository platformPaymentParameterRepository;

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 查询订单类型列表
     *
     * @return 订单类型列表
     */
    @Override
    public List<DropdownItem> listOrderTypes() {
        String key = OrderTypeEnum.class.getSimpleName().concat(".");
        return Arrays.stream(OrderTypeEnum.values()).map(e -> new DropdownItem(e.getCode(), LanguageHolder.getName(key.concat(String.valueOf(e.getCode()))))).collect(Collectors.toList());
    }

    /**
     * 判断订单是否能售后
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canAfterSaleOrder(OrderDO order) {
        //如果是拼团订单：（拼团状态为拼团失败，且订单的外部状态为“待确认发货”） 或 (拼团成功）， 则可以售后
        //如果非拼团订单：已经有收到款或有发货的订单即显示售后按钮（包括状态为已中止的订单）
        return order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) ? ((order.getOuterStatus().equals(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()) && order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_FAILED.getCode())) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_SUCCESS.getCode())) : (order.getHasPaid() || order.getHasDelivered());
    }

    /**
     * 判断采购商是否能取消订单
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerCancelOrder(OrderDO order) {
        //拼团订单“拼团中”时，不能取消或中止
        if(order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && (order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUPING.getCode()) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode()))) {
            return false;
        }

        //支付中的订单不能取消
        if(order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAYING.getCode())) {
            return false;
        }

        //已支付、待归档与已完成订单不能取消或中止订单
        if(order.getHasPaid() || order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_ARCHIVE.getCode()) || order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) || order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) {
            return false;
        } else if (order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_SUBMIT_VALIDATE.getCode()) || order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_SUBMIT.getCode())) {
            //刚创建完毕，没有提交内部审核，没有提交到供应商，显示取消按钮
            return true;
        } else {
            //未签署电子合同且从未收到款且未发过货的订单，显示取消订单按钮
            return !order.getHasPaid() && !order.getHasDelivered() && !order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && order.getContract() == null;
        }
    }

    /**
     * 判断采购商是否能调整送货时间
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerModifyDeliverTime(OrderDO order) {
        //订单状态不为已完成，已取消，已中止且未发货过
        return !(order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode()) || order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) || order.getOuterStatus().equals(OrderOuterStatusEnum.TERMINATED.getCode()) || order.getHasDelivered());
    }

    /**
     * 判断采购商是否能退款订单
     *
     * @param order 订单
     * @return true-是，false-否
     */
    @Override
    public Boolean canBuyerRefundOrder(OrderDO order) {
        //退款条件：订单为拼团订单，外部状态为“已取消”，退款失败，支付记录包含一次100%支付的记录
        return order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && Objects.nonNull(order.getHasRefund()) && !order.getHasRefund() && Objects.nonNull(order.getCanRefund()) && order.getCanRefund();
    }

    /**
     * 判断采购商是否能退款订单
     * @param order 订单
     * @return true-是，false-否
     */
    @Override
    public Boolean canBuyerDeleteOrder(OrderDO order) {
        //删除条件：除拼团订单且订单外部状态为”已取消“且拼团退款失败的订单外，显示”删除“按钮
        return !order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode());
    }

    /**
     * 判断订单是否能取消
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canVendorCancelOrder(OrderDO order) {
        //拼团订单“拼团中”时，不能取消或中止
        if(order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && (order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUPING.getCode()) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode()))) {
            return false;
        }

        //支付中的订单不能取消
        if(order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAYING.getCode())) {
            return false;
        }

        //待归档、已完成的订单不能取消
        if(order.getVendorInnerStatus().equals(VendorInnerStatusEnum.VENDOR_TO_ARCHIVE.getCode()) || order.getVendorInnerStatus().equals(VendorInnerStatusEnum.ACCOMPLISHED.getCode()) || order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) {
            return false;
        }

        //Srm订单没有合同
        if(order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || order.getOrderKind().equals(OrderSourceKindEnum.REQUISITION.getCode())) {
            //从未收到款且未发过货的订单，显示取消订单按钮
            return !order.getHasPaid() && !order.getHasDelivered() && !order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode());
        } else {
            //未签署电子合同且从未收到款且未发过货的订单，显示取消订单按钮
            return !order.getHasPaid() && !order.getHasDelivered() && !order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && order.getContract() == null;
        }
    }

    /**
     * 判断订单是否能中止
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canTerminateOrder(OrderDO order) {
        //拼团订单“拼团中”时，不能取消或中止
        if(order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && (order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUPING.getCode()) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode()))) {
            return false;
        }

        //待归档与已完成订单不能取消或中止订单
        if(order.getVendorInnerStatus().equals(VendorInnerStatusEnum.VENDOR_TO_ARCHIVE.getCode()) || order.getVendorInnerStatus().equals(VendorInnerStatusEnum.ACCOMPLISHED.getCode()) || order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) {
            return false;
        }

        //已签署电子合同或有收过款或有过发货的订单，显示中止订单按钮
        return !order.getOuterStatus().equals(OrderOuterStatusEnum.TERMINATED.getCode()) && (order.getHasPaid() || order.getHasDelivered() || order.getContract() != null);
    }

    /**
     * 判断订单是否能评论
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerCommentOrder(OrderDO order) {
        //已经完成的订单可以被评论
        return !OrderSourceKindEnum.SRM.getCode().equals(order.getOrderKind()) && !order.getBuyerCommented() && order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) && order.getVendorInnerStatus().equals(VendorInnerStatusEnum.ACCOMPLISHED.getCode()) && order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode());
    }

    /**
     * 判断供应商是否能评论订单
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canVendorCommentOrder(OrderDO order) {
        //已经完成的订单可以被评论
        return !order.getVendorCommented() && order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) && order.getVendorInnerStatus().equals(VendorInnerStatusEnum.ACCOMPLISHED.getCode()) && order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode());
    }

    /**
     * 判断订单是否能转单
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canTransferOrder(OrderDO order) {
        //根据是否有上级供应会员显示“转单”按钮：同时：
        // a. 下单模式要为“进货单下单”，“询价报价下单”
        // b. 外部状态不等于 已完成、已取消、已中止，订单未进行过转单操作
        // c. 订单如果已经发过货，不能转单
        return !order.getHasDelivered() && ((order.getOrderMode().equals(OrderModeEnum.BUYER.getCode()) || order.getOrderMode().equals(OrderModeEnum.CHANNEL_DIRECT_BUY.getCode()) || order.getOrderMode().equals(OrderModeEnum.CHANNEL_STOCK_BUY.getCode()) || order.getOrderMode().equals(OrderModeEnum.QUOTATION.getCode())) && !order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode()) && !order.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && !order.getOuterStatus().equals(OrderOuterStatusEnum.TERMINATED.getCode()) && NumberUtil.notNullAndPositive(order.getSupplyMemberId()) && NumberUtil.notNullAndPositive(order.getSupplyRoleId()) && NumberUtil.isNullOrZero(order.getRelationId()));
    }

    /**
     * 判断订单是否能修改订单价格
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canVendorModifyOrderPrice(OrderDO order) {
        //当前销售订单从未支付过而且从未发过货，订单类型为现货采购与询报价采购且外部状态不等于已中止、已取消
        return (order.getOuterStatus() < OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode() && !order.getHasDelivered()) && ((OrderTypeEnum.SPOT_PURCHASING.getCode().equals(order.getOrderType()) || OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode().equals(order.getOrderType()))
                && !(OrderOuterStatusEnum.TERMINATED.getCode().equals(order.getOuterStatus()) || OrderOuterStatusEnum.CANCELLED.getCode().equals(order.getOuterStatus())) || (!order.getHasPaid() && order.getOuterStatus() <= OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()));
    }

    /**
     * 判断订单是否能修改订单
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canVendorModifyOrder(OrderDO order) {
        //当前销售订单从未支付过且从未发过货，订单类型为现货采购、渠道直采、渠道现货且外部状态不等于已中止、已取消
        return (order.getOuterStatus() < OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode() && !order.getHasDelivered()) && ((OrderTypeEnum.SPOT_PURCHASING.getCode().equals(order.getOrderType()) || OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode().equals(order.getOrderType()) || OrderTypeEnum.CHANNEL_SPOT.getCode().equals(order.getOrderType()))
                && !(OrderOuterStatusEnum.TERMINATED.getCode().equals(order.getOuterStatus()) || OrderOuterStatusEnum.CANCELLED.getCode().equals(order.getOuterStatus())) || (!order.getHasPaid() && order.getOuterStatus() <= OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()));
    }

    /**
     * 判断是否能申请开票
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canApplyInvoice(OrderDO order) {
        //订单类型为非积分订单，非渠道积分订单，非SRM订单且订单未勾选需要发票
        return !(OrderTypeEnum.CREDITS_EXCHANGE.getCode().equals(order.getOrderType()) || OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode().equals(order.getOrderType()) || OrderSourceKindEnum.SRM.getCode().equals(order.getOrderKind())) && (order.getInvoice() == null || !order.getInvoice().getDefaultInvoice());
    }

    /**
     * 根据商城类型判断订单类型、订单模式
     *
     * @param shopType 商城类型枚举
     * @return 订单类型、订单模式
     */
    @Override
    public OrderTypeModeBO findOrderTypeMode(Integer shopType) {
        //如当前商城类型为企业商城，则生成的订单下单模式为进货单下单，订单类型为现货采购，
        //如当前商城类型为渠道商城，则生成的订单下单模式为渠道直采进货单下单，订单类型为渠道直采，
        //如当前商城类型为渠道自有商城，则生成的订单下单模式为渠道现货进货单下单，订单类型为渠道现货
        //如当前商城类型为（企业）积分商城，则生成的订单下单模式为积分下单，订单类型为积分兑换，
        //如当前商城类型为渠道积分商城，则生成的订单下单模式为渠道积分下单，订单类型为渠道积分兑换，
        switch (ShopTypeEnum.parseCode(shopType)) {
            case ENTERPRISE:
                return new OrderTypeModeBO(OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderModeEnum.BUYER.getCode());
            case CHANNEL:
                return new OrderTypeModeBO(OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(), OrderModeEnum.CHANNEL_DIRECT_BUY.getCode());
            case CHANNEL_SELF:
                return new OrderTypeModeBO(OrderTypeEnum.CHANNEL_SPOT.getCode(), OrderModeEnum.CHANNEL_STOCK_BUY.getCode());
            case SCORE:
                return new OrderTypeModeBO(OrderTypeEnum.CREDITS_EXCHANGE.getCode(), OrderModeEnum.RIGHT_POINT.getCode());
            case CHANNEL_SCORE:
                return new OrderTypeModeBO(OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode(), OrderModeEnum.CHANNEL_RIGHT_POINT.getCode());
            default:
                break;
        }

        return new OrderTypeModeBO();
    }

    /**
     * 判断供应商是否能生成支付链接
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canVendorGeneratePayLink(OrderDO order) {
        //当前销售订单的外部状态为“待支付”
        return OrderOuterStatusEnum.TO_PAY.getCode().equals(order.getOuterStatus());
    }

    /**
     * 采购商是否能“邀请拼团”
     *
     * @param order 订单
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerInviteGroup(OrderDO order) {
        //订单为拼团订单、且外部状态为“待确认发货”， 且没有发过货，且拼团状态为“拼团中”
        return order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && order.getOuterStatus().equals(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()) && !order.getHasDelivered() && order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode());
    }

    /**
     * 采购商用户是否能领取“待分配订单”
     *
     * @param order 订单
     * @return true - 是，false-否
     */
    @Override
    public Boolean canBuyerTakeOrder(OrderDO order) {
        //“代客下单”订单，并且buyerUserId为Null或0时，才能领取
        return NumberUtil.isNullOrZero(order.getBuyerUserId()) && order.getOrderKind().equals(OrderSourceKindEnum.AGENT.getCode());
    }

    /**
     * 供应商用户是否能领取“待分配订单”
     *
     * @param order 订单
     * @return true-是，false-否
     */
    @Override
    public Boolean canVendorTakeOrder(OrderDO order) {
        //vendorUserId为Null或0时，才能领取
        return NumberUtil.isNullOrZero(order.getVendorUserId());
    }

    /**
     * 订单是否已经提交给了供应商
     *
     * @param order 订单
     * @return true-是，false-否
     */
    @Override
    public Boolean hasSubmittedToVendor(OrderDO order) {
        //以外部状态“待提交”作判断，订单是否已经提交给供应商
        //如果外部状态为“待提交”，表示订单处于采购商审核过程中，否则表示订单已经提交给了“供应商”
        return !order.getOuterStatus().equals(OrderOuterStatusEnum.TO_SUBMIT.getCode());
    }

    /**
     * （采购订单）根据供应商分组采购订单，进行拆单
     *
     * @param products 订单商品列表
     * @return 供应商、上级供应商分组
     */
    @Override
    public Map<OrderSeparateDTO, List<OrderProductVO>> separateBuyerOrder(List<OrderProductVO> products) {
        return products.stream().collect(Collectors.groupingBy(p -> new OrderSeparateDTO(p.getVendorMemberId(), p.getVendorRoleId(), p.getVendorMemberName(), p.getSupplyMemberId(), p.getSupplyRoleId(), p.getSupplyMemberName())));
    }

    /**
     * （App订单）根据供应商分组采购订单，进行拆单
     *
     * @param products 订单商品列表
     * @return 供应商、上级供应商分组
     */
    @Override
    public Map<OrderSeparateDTO, List<MobileOrderProductVO>> separateMobileOrder(List<MobileOrderProductVO> products) {
        return products.stream().collect(Collectors.groupingBy(p -> new OrderSeparateDTO(p.getVendorMemberId(), p.getVendorRoleId(), p.getVendorMemberName(), p.getSupplyMemberId(), p.getSupplyRoleId(), p.getSupplyMemberName())));
    }

    /**
     * （B2B订单）根据供应商分组B2B订单，进行拆单
     *
     * @param vendorMemberId   供应会员Id
     * @param vendorRoleId     供应会员角色Id
     * @param vendorMemberName 供应会员名称
     * @param products         订单商品列表
     * @return 供应商、上级供应商分组
     */
    @Override
    public Map<OrderSeparateDTO, List<BusinessOrderProductVO>> separateBusinessOrder(Long vendorMemberId, Long vendorRoleId, String vendorMemberName, List<BusinessOrderProductVO> products) {
        return products.stream().collect(Collectors.groupingBy(p -> new OrderSeparateDTO(vendorMemberId, vendorRoleId, vendorMemberName, p.getSupplyMemberId(), p.getSupplyRoleId(), p.getSupplyMemberName())));
    }

    /**
     * （现货采购订单）根据供应商分组现货采购订单，进行拆单
     *
     * @param vendorMemberId   供应会员Id
     * @param vendorRoleId     供应会员角色Id
     * @param vendorMemberName 供应会员名称
     * @param products         订单商品列表
     * @return 供应商、上级供应商分组
     */
    @Override
    public Map<OrderSeparateDTO, List<PurchaseOrderProductVO>> separatePurchaseOrder(Long vendorMemberId, Long vendorRoleId, String vendorMemberName, List<PurchaseOrderProductVO> products) {
        return products.stream().collect(Collectors.groupingBy(p -> new OrderSeparateDTO(vendorMemberId, vendorRoleId, vendorMemberName, p.getSupplyMemberId(), p.getSupplyRoleId(), p.getSupplyMemberName())));
    }

    /**
     * 分页查询采购订单（新增后，可修改，尚未提交的订单）
     *
     * @param buyerMemberId    采购会员Id
     * @param buyerRoleId      采购会员角色Id
     * @param orderNo          订单编号
     * @param digest           订单摘要
     * @param vendorMemberName 供应会员名称
     * @param startDate        订单起始日期
     * @param endDate          订单结束日期
     * @param orderTypes       订单类型枚举列表
     * @param current          当前页
     * @param pageSize         每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageCreatedOrders(Long buyerMemberId, Long buyerRoleId, String orderNo, String digest, String vendorMemberName, String startDate, String endDate, List<OrderTypeEnum> orderTypes, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (Specification<OrderDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("buyerMemberId").as(Long.class), buyerMemberId));
            list.add(criteriaBuilder.equal(root.get("buyerRoleId").as(Long.class), buyerRoleId));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //供应会员名称
            if(StringUtils.hasLength(vendorMemberName)) {
                list.add(criteriaBuilder.like(root.get("vendorMemberName").as(String.class), "%" + vendorMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //采购商内部状态
            list.add(criteriaBuilder.equal(root.get("buyerInnerStatus").as(Integer.class), BuyerInnerStatusEnum.BUYER_TO_SUBMIT_VALIDATE.getCode()));


            //订单类型
            if(!CollectionUtils.isEmpty(orderTypes)) {
                if(orderTypes.size() == 1) {
                    list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderTypes.get(0).getCode()));
                } else {
                    List<Predicate> orList = orderTypes.stream().map(orderType -> criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType.getCode())).collect(Collectors.toList());
                    Predicate[] orPredicates = new Predicate[orList.size()];
                    list.add(criteriaBuilder.or(orList.toArray(orPredicates)));
                }
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 分页查询待分配采购订单
     *
     * @param buyerMemberId    采购会员Id
     * @param buyerRoleId      采购会员角色Id
     * @param orderNo          订单编号
     * @param digest           订单摘要
     * @param vendorMemberName 供应会员名称
     * @param startDate        订单起始日期
     * @param endDate          订单结束日期
     * @param orderType        订单类型枚举
     * @param current          当前页
     * @param pageSize         每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageBuyerToTakeOrders(Long buyerMemberId, Long buyerRoleId, String orderNo, String digest, String vendorMemberName, String startDate, String endDate, Integer orderType, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (Specification<OrderDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("buyerMemberId").as(Long.class), buyerMemberId));
            list.add(criteriaBuilder.equal(root.get("buyerRoleId").as(Long.class), buyerRoleId));
            //查询“代客下单”订单，且未领取的订单（buyerUserId字段为Null或0）
            list.add(criteriaBuilder.or(criteriaBuilder.isNull(root.get("buyerUserId").as(Long.class)), criteriaBuilder.equal(root.get("buyerUserId").as(Long.class), 0L)));
            list.add(criteriaBuilder.equal(root.get("orderKind").as(Integer.class), OrderSourceKindEnum.AGENT.getCode()));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //供应会员名称
            if(StringUtils.hasLength(vendorMemberName)) {
                list.add(criteriaBuilder.like(root.get("vendorMemberName").as(String.class), "%" + vendorMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType));
            }



            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 分页查询采购订单
     *
     * @param buyerMemberId    采购会员Id
     * @param buyerRoleId      采购会员角色Id
     * @param orderNo          订单编号
     * @param digest           订单摘要
     * @param vendorMemberName 供应会员名称
     * @param startDate        订单起始日期
     * @param endDate          订单结束日期
     * @param orderType        订单类型枚举
     * @param buyerInnerStatus 采购会员内部状态
     * @param outerStatus      订单外部状态
     * @param current          当前页
     * @param pageSize         每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageBuyerOrders(Long buyerMemberId, Long buyerRoleId, String orderNo, String digest, String vendorMemberName, String startDate, String endDate, Integer orderType, Integer buyerInnerStatus, Integer outerStatus, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (Specification<OrderDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("buyerMemberId").as(Long.class), buyerMemberId));
            list.add(criteriaBuilder.equal(root.get("buyerRoleId").as(Long.class), buyerRoleId));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //供应会员名称
            if(StringUtils.hasLength(vendorMemberName)) {
                list.add(criteriaBuilder.like(root.get("vendorMemberName").as(String.class), "%" + vendorMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            //采购商内部状态
            if(NumberUtil.notNullOrZero(buyerInnerStatus)) {
                list.add(criteriaBuilder.equal(root.get("buyerInnerStatus").as(Integer.class), buyerInnerStatus));
            }

            //外部状态
            if(NumberUtil.notNullOrZero(outerStatus)) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), outerStatus));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 分页查询待分配销售订单
     * @param vendorMemberId  供应会员Id
     * @param vendorRoleId    供应会员角色Id
     * @param storeIds         门店ids
     * @param orderNo         订单编号
     * @param digest          订单摘要
     * @param buyerMemberName 采购会员名称
     * @param startDate       订单起始日期
     * @param endDate         订单结束日期
     * @param orderType       订单类型枚举
     * @param current         当前页
     * @param pageSize        每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageVendorToTakeOrders(Long vendorMemberId, Long vendorRoleId, List<Long> storeIds, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderType, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("vendorMemberId").as(Long.class), vendorMemberId));
            list.add(criteriaBuilder.equal(root.get("vendorRoleId").as(Long.class), vendorRoleId));
            //不查询采购商未提交的订单
            list.add(criteriaBuilder.greaterThan(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));
            //待分配订单的vendorUserId字段为Null或0
            list.add(criteriaBuilder.or(criteriaBuilder.isNull(root.get("vendorUserId").as(Long.class)), criteriaBuilder.equal(root.get("vendorUserId").as(Long.class), 0L)));

            //用户关联门店id
            if (CollUtil.isNotEmpty(storeIds)) {
                list.add(criteriaBuilder.in(root.get("storeId")).value(new HashSet<>(storeIds)));
            }

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //采购会员名称
            if(StringUtils.hasLength(buyerMemberName)) {
                list.add(criteriaBuilder.like(root.get("buyerMemberName").as(String.class), "%" + buyerMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 分页查询销售订单
     *
     * @param vendorMemberId        供应会员Id
     * @param vendorRoleId          供应会员角色Id
     * @param orderNo               订单编号
     * @param digest                订单摘要
     * @param buyerMemberName       采购会员名称
     * @param startDate             订单起始日期
     * @param endDate               订单结束日期
     * @param orderType             订单类型枚举
     * @param vendorInnerStatus     供应会员内部状态
     * @param outerStatus           订单外部状态
     * @param current               当前页
     * @param pageSize              每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageVendorOrders(Long vendorMemberId, Long vendorRoleId, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderType, Integer vendorInnerStatus, Integer outerStatus, int current, int pageSize) {
        return pageVendorOrders(vendorMemberId, vendorRoleId, orderNo, digest, buyerMemberName, startDate, endDate, orderType, NumberUtil.isNullOrZero(vendorInnerStatus) ? new ArrayList<>() : Collections.singletonList(vendorInnerStatus), outerStatus, current, pageSize);
    }

    /**
     * 分页查询销售订单
     *
     * @param vendorMemberId      供应会员Id
     * @param vendorRoleId        供应会员角色Id
     * @param orderNo             订单编号
     * @param digest              订单摘要
     * @param buyerMemberName     采购会员名称
     * @param startDate           订单起始日期
     * @param endDate             订单结束日期
     * @param orderType           订单类型枚举
     * @param vendorInnerStatuses 供应会员内部状态
     * @param outerStatus         订单外部状态
     * @param current             当前页
     * @param pageSize            每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageVendorOrders(Long vendorMemberId, Long vendorRoleId, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderType, List<Integer> vendorInnerStatuses, Integer outerStatus, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (Specification<OrderDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("vendorMemberId").as(Long.class), vendorMemberId));
            list.add(criteriaBuilder.equal(root.get("vendorRoleId").as(Long.class), vendorRoleId));
            //不查询采购商未提交的订单
            //list.add(criteriaBuilder.notEqual(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));
            list.add(criteriaBuilder.greaterThan(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //采购会员名称
            if(StringUtils.hasLength(buyerMemberName)) {
                list.add(criteriaBuilder.like(root.get("buyerMemberName").as(String.class), "%" + buyerMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            //供应商内部状态
            if(!CollectionUtils.isEmpty(vendorInnerStatuses)) {
                if(vendorInnerStatuses.size() == 1) {
                    list.add(criteriaBuilder.equal(root.get("vendorInnerStatus").as(Integer.class), vendorInnerStatuses.get(0)));
                } else {
                    list.add(root.get("vendorInnerStatus").as(Integer.class).in(vendorInnerStatuses));
                }
            }

            //外部状态
            if(NumberUtil.notNullOrZero(outerStatus)) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), outerStatus));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 分页查询待核销订单
     * @param vendorMemberId      供应会员Id
     * @param vendorRoleId        供应会员角色Id
     * @param orderNo             订单编号
     * @param digest              订单摘要
     * @param buyerMemberName     采购会员名称
     * @param startDate           订单起始日期
     * @param endDate             订单结束日期
     * @param orderType           订单类型枚举
     * @param vendorInnerStatuses 供应会员内部状态
     * @param outerStatus         订单外部状态
     * @param current             当前页
     * @param pageSize            每页行数
     * @return 查询结果
     */
    @Override
    public Page<OrderDO> pageVendorPickUpOrders(Long vendorMemberId, Long vendorRoleId, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderType, Integer vendorInnerStatuses, Integer outerStatus, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("vendorMemberId").as(Long.class), vendorMemberId));
            list.add(criteriaBuilder.equal(root.get("vendorRoleId").as(Long.class), vendorRoleId));

            list.add(criteriaBuilder.equal(root.get("pickUp").as(Boolean.class), Boolean.TRUE));
            //不查询采购商未提交的订单
            list.add(criteriaBuilder.greaterThan(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //采购会员名称
            if(StringUtils.hasLength(buyerMemberName)) {
                list.add(criteriaBuilder.like(root.get("buyerMemberName").as(String.class), "%" + buyerMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(criteriaBuilder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            //供应商内部状态
            if (NumberUtil.notNullOrZero(vendorInnerStatuses)) {
                list.add(root.get("vendorInnerStatus").as(Integer.class).in(vendorInnerStatuses));
            }

            //外部状态
            if (NumberUtil.notNullOrZero(outerStatus)) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), outerStatus));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }

    /**
     * 全量查询采购订单(导出excel)
     * @param buyerMemberId      采购会员Id
     * @param buyerRoleId        采购会员角色Id
     * @param orderNo            订单编号
     * @param digest             订单摘要
     * @param vendorMemberName   供应会员名称
     * @param startDate          订单起始日期
     * @param endDate            订单结束日期
     * @param orderType          订单类型枚举
     * @param buyerInnerStatuses 采购会员内部状态
     * @param outerStatus        订单外部状态
     * @return 查询结果
     */
    @Override
    public List<OrderDO> exportBuyerOrders(Long buyerMemberId, Long buyerRoleId, String orderNo, String digest, String vendorMemberName, String startDate, String endDate, Integer orderType, List<Integer> buyerInnerStatuses, Integer outerStatus) {
        Specification<OrderDO> specification = (root, query, builder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(builder.equal(root.get("buyerMemberId").as(Long.class), buyerMemberId));
            list.add(builder.equal(root.get("buyerRoleId").as(Long.class), buyerRoleId));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(builder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(builder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //供应会员名称
            if(StringUtils.hasLength(vendorMemberName)) {
                list.add(builder.like(root.get("vendorMemberName").as(String.class), "%" + vendorMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(builder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(builder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(builder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            //采购商内部状态
            if(!CollectionUtils.isEmpty(buyerInnerStatuses)) {
                if(buyerInnerStatuses.size() == 1) {
                    list.add(builder.equal(root.get("buyerInnerStatus").as(Integer.class), buyerInnerStatuses.get(0)));
                } else {
                    list.add(root.get("buyerInnerStatus").as(Integer.class).in(buyerInnerStatuses));
                }
            }

            //外部状态
            if(NumberUtil.notNullOrZero(outerStatus)) {
                list.add(builder.equal(root.get("outerStatus").as(Integer.class), outerStatus));
            }

            Predicate[] p = new Predicate[list.size()];
            return builder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, Sort.by("id").descending());
    }

    /**
     * 全量查询销售订单(导出excel)
     * @param vendorMemberId      供应会员Id
     * @param vendorRoleId        供应会员角色Id
     * @param orderNo             订单编号
     * @param digest              订单摘要
     * @param buyerMemberName     采购会员名称
     * @param startDate           订单起始日期
     * @param endDate             订单结束日期
     * @param orderType           订单类型枚举
     * @param vendorInnerStatuses 供应会员内部状态
     * @param outerStatus         订单外部状态
     * @return 查询结果
     */
    @Override
    public List<OrderDO> exportVendorOrders(Long vendorMemberId, Long vendorRoleId, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderType, List<Integer> vendorInnerStatuses, Integer outerStatus) {
        Specification<OrderDO> specification = (root, query, builder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(builder.equal(root.get("vendorMemberId").as(Long.class), vendorMemberId));
            list.add(builder.equal(root.get("vendorRoleId").as(Long.class), vendorRoleId));
            //不查询采购商未提交的订单
            //list.add(builder.notEqual(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));
            list.add(builder.greaterThan(root.get("vendorInnerStatus").as(Integer.class), VendorInnerStatusEnum.WAITING_FOR_BUYER_SUBMIT.getCode()));

            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(builder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(builder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //采购会员名称
            if(StringUtils.hasLength(buyerMemberName)) {
                list.add(builder.like(root.get("buyerMemberName").as(String.class), "%" + buyerMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(builder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(builder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderType)) {
                list.add(builder.equal(root.get("orderType").as(Integer.class), orderType));
            }

            //供应商内部状态
            if(!CollectionUtils.isEmpty(vendorInnerStatuses)) {
                if(vendorInnerStatuses.size() == 1) {
                    list.add(builder.equal(root.get("vendorInnerStatus").as(Integer.class), vendorInnerStatuses.get(0)));
                } else {
                    list.add(root.get("vendorInnerStatus").as(Integer.class).in(vendorInnerStatuses));
                }
            }

            //外部状态
            if(NumberUtil.notNullOrZero(outerStatus)) {
                list.add(builder.equal(root.get("outerStatus").as(Integer.class), outerStatus));
            }

            Predicate[] p = new Predicate[list.size()];
            return builder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, Sort.by("id").descending());
    }

    /**
     * 查询采购订单详情
     *
     * @param order                订单
     * @param buyerInnerStatusEnum 采购商内部状态
     * @return 订单详情
     */
    @Override
    public Wrapper<BuyerOrderDetailVO> getBuyerOrderDetail(OrderDO order, BuyerInnerStatusEnum buyerInnerStatusEnum) {
        return getBuyerOrderDetail(order, Collections.singletonList(buyerInnerStatusEnum));
    }

    /**
     * 查询采购订单详情
     *
     * @param order                 订单
     * @param buyerInnerStatusEnums 采购商内部状态列表
     * @return 订单详情
     */
    @Override
    public Wrapper<BuyerOrderDetailVO> getBuyerOrderDetail(OrderDO order, List<BuyerInnerStatusEnum> buyerInnerStatusEnums) {
        if(buyerInnerStatusEnums.stream().noneMatch(buyerInnerStatusEnum -> buyerInnerStatusEnum.getCode().equals(order.getBuyerInnerStatus()))) {
            return Wrapper.fail(ResponseCode.ORDER_STATUS_IS_NOT_MATCHED);
        }
        return getBuyerOrderDetail(order);
    }

    /**
     * 查询采购订单详情
     *
     * @param order 订单
     * @return 订单详情
     */
    @Override
    public Wrapper<BuyerOrderDetailVO> getBuyerOrderDetail(OrderDO order) {
        //调用工作流服务接口，查询流程步骤定义
        Wrapper<ProcessStepsBO> stepResult = baseOrderTaskService.listOrderProcessSteps(order.getTask().getProcessKey(), order.getTask().getTaskId(), order.getVendorMemberId(), order.getVendorRoleId(), order.getBuyerRoleId(), OrderServiceContants.BUYER_VALIDATE_EXTERNAL_TASK_NAME);
        if(stepResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(stepResult.getCode(), stepResult.getMessage());
        }

        BuyerOrderDetailVO detailVO = new BuyerOrderDetailVO();
        //基本信息
        detailVO.setOuterSteps(stepResult.getData().getOuterSteps());
        detailVO.setCurrentOuterStep(stepResult.getData().getCurrentOuterStep());
        detailVO.setInnerSteps(stepResult.getData().getInnerSteps());
        detailVO.setCurrentInnerStep(stepResult.getData().getCurrentInnerStep());
        detailVO.setOrderId(order.getId());
        detailVO.setOrderNo(order.getOrderNo());
        detailVO.setCreateTime(order.getCreateTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
        detailVO.setQuoteId(order.getQuoteId());
        detailVO.setQuoteNo(order.getQuoteNo());
        detailVO.setDigest(order.getDigest());
        detailVO.setOrderTypeName(OrderTypeEnum.getNameByCode(order.getOrderType()));
        detailVO.setOrderMode(order.getOrderMode());
        detailVO.setOrderModeName(OrderModeEnum.getNameByCode(order.getOrderMode()));
        detailVO.setOrderKind(order.getOrderKind());
        detailVO.setShopId(order.getShopId());
        detailVO.setShopName(order.getShopName());
        detailVO.setInnerStatus(order.getBuyerInnerStatus());
        detailVO.setInnerStatusName(BuyerInnerStatusEnum.getNameByCode(order.getBuyerInnerStatus()));
        detailVO.setOuterStatus(order.getOuterStatus());
        detailVO.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(order.getOuterStatus()));
        detailVO.setVendorMemberId(order.getVendorMemberId());
        detailVO.setVendorRoleId(order.getVendorRoleId());
        detailVO.setVendorMemberName(order.getVendorMemberName());
        //营销活动状态
        detailVO.setGroupOrder(NumberUtil.notNullOrZero(order.getOrderKind()) && order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()));
        detailVO.setPromotionStatus(NumberUtil.isNullOrZero(order.getPromotionStatus()) ? 0 : order.getPromotionStatus());
        detailVO.setPromotionStatusName(OrderPromotionStatusEnum.getNameByCode(detailVO.getPromotionStatus()));

        //订单商品汇总、发货汇总
        OrderProductSummaryBO summaryBO = baseOrderProductService.summaryOrderProducts(order);
        detailVO.setReceiveDone(summaryBO.getReceiveDone());
        detailVO.setProduct(summaryBO.getProductSummary());
        detailVO.setDeliveries(summaryBO.getDeliverySummaries());
        //支付记录
        detailVO.setPayments(baseOrderPaymentService.findBuyerOrderPayments(order));
        //交付信息
        detailVO.setConsignee(baseOrderConsigneeService.getOrderConsignee(order));
        //合同信息
        detailVO.setContract(baseOrderContractService.getOrderContract(order));
        detailVO.setHasContract(detailVO.getContract() != null);
        //发票信息
        detailVO.setInvoice(baseOrderInvoiceService.getOrderInvoice(order));
        detailVO.setHasInvoice(detailVO.getInvoice() != null);
        //其他要求
        detailVO.setRequirement(baseOrderRequirementService.getOrderRequirement(order));
        //收发货明细
        detailVO.setDeliveryDetails(baseOrderDeliveryService.listBuyerOrderDeliveryDetails(order));
        //内部流转记录
        detailVO.setInnerHistories(baseOrderHistoryService.listBuyerOrderInnerHistories(order));
        //外部流转记录
        detailVO.setOuterHistories(baseOrderHistoryService.listOrderOuterHistories(order));
        //是否显示“申请开票“按钮
        detailVO.setShowApplyInvoice(baseOrderService.canApplyInvoice(order));
        //是否显示“税费”
        detailVO.setShowTaxes(OrderTypeEnum.COMMERCE_IMPORT.getCode().equals(order.getOrderType()));
        return Wrapper.success(detailVO);
    }

    /**
     * 查询供应订单详情
     *
     * @param order                 订单
     * @param vendorInnerStatusEnum 供应商内部状态
     * @return 查询结果
     */
    @Override
    public Wrapper<VendorOrderDetailVO> getVendorOrderDetail(OrderDO order, VendorInnerStatusEnum vendorInnerStatusEnum) {
        return getVendorOrderDetail(order, Collections.singletonList(vendorInnerStatusEnum));
    }

    /**
     * 查询供应订单详情
     *
     * @param order                  订单
     * @param vendorInnerStatusEnums 供应商内部状态列表
     * @return 查询结果
     */
    @Override
    public Wrapper<VendorOrderDetailVO> getVendorOrderDetail(OrderDO order, List<VendorInnerStatusEnum> vendorInnerStatusEnums) {
        if(vendorInnerStatusEnums.stream().noneMatch(vendorInnerStatusEnum -> vendorInnerStatusEnum.getCode().equals(order.getVendorInnerStatus()))) {
            return Wrapper.fail(ResponseCode.ORDER_STATUS_IS_NOT_MATCHED);
        }

        return getVendorOrderDetail(order);
    }

    /**
     * 查询供应订单详情
     *
     * @param order 订单
     * @return 查询结果
     */
    @Override
    public Wrapper<VendorOrderDetailVO> getVendorOrderDetail(OrderDO order) {
        //调用工作流服务接口，查询流程步骤定义
        Wrapper<ProcessStepsBO> stepResult = baseOrderTaskService.listOrderProcessSteps(order.getTask().getProcessKey(), order.getTask().getTaskId(), order.getVendorMemberId(), order.getVendorRoleId(), order.getBuyerRoleId(), OrderServiceContants.VENDOR_VALIDATE_EXTERNAL_TASK_NAME);
        if(stepResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(stepResult.getCode(), stepResult.getMessage());
        }

        VendorOrderDetailVO detailVO = new VendorOrderDetailVO();
        //基本信息
        detailVO.setOuterSteps(stepResult.getData().getOuterSteps());
        detailVO.setCurrentOuterStep(stepResult.getData().getCurrentOuterStep());
        detailVO.setInnerSteps(stepResult.getData().getInnerSteps());
        detailVO.setCurrentInnerStep(stepResult.getData().getCurrentInnerStep());
        detailVO.setOrderId(order.getId());
        detailVO.setOrderNo(order.getOrderNo());
        detailVO.setCreateTime(order.getCreateTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
        detailVO.setQuoteId(order.getQuoteId());
        detailVO.setQuoteNo(order.getQuoteNo());
        detailVO.setDigest(order.getDigest());
        detailVO.setOrderTypeName(OrderTypeEnum.getNameByCode(order.getOrderType()));
        detailVO.setOrderMode(order.getOrderMode());
        detailVO.setOrderModeName(OrderModeEnum.getNameByCode(order.getOrderMode()));
        detailVO.setOrderKind(order.getOrderKind());
        detailVO.setShopName(order.getShopName());
        detailVO.setInnerStatus(order.getVendorInnerStatus());
        detailVO.setInnerStatusName(VendorInnerStatusEnum.getNameByCode(order.getVendorInnerStatus()));
        detailVO.setOuterStatus(order.getOuterStatus());
        detailVO.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(order.getOuterStatus()));
        detailVO.setBuyerMemberName(order.getBuyerMemberName());

        //订单商品汇总、发货汇总
        OrderProductSummaryBO summaryBO = baseOrderProductService.summaryOrderProducts(order);
        detailVO.setDeliveryDone(summaryBO.getDeliveryDone());
        detailVO.setProduct(summaryBO.getProductSummary());
        detailVO.setDeliveries(summaryBO.getDeliverySummaries());
        //支付记录
        detailVO.setPayments(baseOrderPaymentService.findVendorOrderPayments(order));
        //交付信息
        detailVO.setConsignee(baseOrderConsigneeService.getOrderConsignee(order));
        //合同信息
        detailVO.setContract(baseOrderContractService.getOrderContract(order));
        detailVO.setHasContract(detailVO.getContract() != null);
        //发票信息
        detailVO.setInvoice(baseOrderInvoiceService.getOrderInvoice(order));
        detailVO.setHasInvoice(detailVO.getInvoice() != null);
        //其他要求
        detailVO.setRequirement(baseOrderRequirementService.getOrderRequirement(order));
        //收发货明细
        detailVO.setDeliveryDetails(baseOrderDeliveryService.listVendorOrderDeliveryDetails(order));
        //内部流转记录
        detailVO.setInnerHistories(baseOrderHistoryService.listVendorOrderInnerHistories(order));
        //外部流转记录
        detailVO.setOuterHistories(baseOrderHistoryService.listOrderOuterHistories(order));

        return Wrapper.success(detailVO);
    }

    /**
     * 平台后台 - 查询订单详情
     *
     * @param order 订单
     * @return 查询结果
     */
    @Override
    public Wrapper<PlatformOrderDetailVO> getOrderDetail(OrderDO order) {
        Wrapper<ProcessStepsBO> stepResult = baseOrderTaskService.listOrderProcessSteps(order.getTask().getProcessKey(), order.getTask().getTaskId(), order.getVendorMemberId(), order.getVendorRoleId(), order.getBuyerRoleId(), "");
        if(stepResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(stepResult.getCode(), stepResult.getMessage());
        }

        PlatformOrderDetailVO detailVO = new PlatformOrderDetailVO();
        //基本信息
        detailVO.setOuterSteps(stepResult.getData().getOuterSteps());
        detailVO.setCurrentOuterStep(stepResult.getData().getCurrentOuterStep());
        detailVO.setOrderId(order.getId());
        detailVO.setBuyerMemberId(order.getBuyerMemberId());
        detailVO.setBuyerRoleId(order.getBuyerRoleId());
        detailVO.setBuyerMemberName(order.getBuyerMemberName());
        detailVO.setVendorMemberId(order.getVendorMemberId());
        detailVO.setVendorRoleId(order.getVendorRoleId());
        detailVO.setVendorMemberName(detailVO.getVendorMemberName());

        detailVO.setOrderNo(order.getOrderNo());
        detailVO.setCreateTime(order.getCreateTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
        detailVO.setQuoteId(order.getQuoteId());
        detailVO.setQuoteNo(order.getQuoteNo());
        detailVO.setDigest(order.getDigest());
        detailVO.setOrderTypeName(OrderTypeEnum.getNameByCode(order.getOrderType()));
        detailVO.setOrderType(order.getOrderType());
        detailVO.setOrderMode(order.getOrderMode());
        detailVO.setOrderModeName(OrderModeEnum.getNameByCode(order.getOrderMode()));
        detailVO.setOrderKind(order.getOrderKind());
        detailVO.setShopName(order.getShopName());
        detailVO.setOuterStatus(order.getOuterStatus());
        detailVO.setOuterStatusName(OrderOuterStatusEnum.getNameByCode(order.getOuterStatus()));

        //订单商品汇总、发货汇总
        OrderProductSummaryBO summaryBO = baseOrderProductService.summaryOrderProducts(order);
        detailVO.setProduct(summaryBO.getProductSummary());
        detailVO.setDeliveries(summaryBO.getDeliverySummaries());
        //支付记录
        detailVO.setPayments(baseOrderPaymentService.findPlatformOrderPayments(order));
        //交付信息
        detailVO.setConsignee(baseOrderConsigneeService.getOrderConsignee(order));
        //合同信息
        detailVO.setContract(baseOrderContractService.getOrderContract(order));
        detailVO.setHasContract(detailVO.getContract() != null);
        //发票信息
        detailVO.setInvoice(baseOrderInvoiceService.getOrderInvoice(order));
        detailVO.setHasInvoice(detailVO.getInvoice() != null);
        //其他要求
        detailVO.setRequirement(baseOrderRequirementService.getOrderRequirement(order));
        //收发货明细
        detailVO.setDeliveryDetails(baseOrderDeliveryService.listOrderDeliveryDetails(order));
        //外部流转记录
        detailVO.setOuterHistories(baseOrderHistoryService.listOrderOuterHistories(order));

        return Wrapper.success(detailVO);
    }


    /**
     * 订单创建完成后，扣减库存
     *
     * @param order 订单
     */
    @Override
    public Wrapper<Void> deduceInventory(OrderDO order) {
        if(order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || OrderSourceKindEnum.REQUISITION.getCode().equals(order.getOrderKind())) {
            return Wrapper.success();
        }

        //扣减和返还库存，用的是下单会员的id
        return productFeignService.deductInventory(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getId(), order.getShopId(), order.getShopType(), order.getProducts().stream().map(product -> new InventoryProductBO(product.getProductId(), product.getSkuId(), product.getStockId(), product.getName(), product.getQuantity())).collect(Collectors.toList()));
    }

    /**
     * 订单中止后，返还库存
     *
     * @param order 订单
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> resumeInventory(OrderDO order) {
        if(order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || order.getOrderKind().equals(OrderSourceKindEnum.REQUISITION.getCode())) {
            return Wrapper.success();
        }

        //扣减和返还库存，用的是下单会员的id
        return productFeignService.resumeInventory(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getId(), order.getShopId(), order.getShopType(), order.getProducts().stream().map(product -> new InventoryProductBO(product.getProductId(), product.getSkuId(), product.getStockId(), product.getName(), product.getLeftCount())).collect(Collectors.toList()));
    }

    /**
     * 下单成功后，删除购物车
     *
     * @param shopType 商城类型
     * @param cartIds  购物车Id列表
     */
    @Override
    public void emptyProductCarts(Integer shopType, List<Long> cartIds) {
        List<Long> filterCartIds = cartIds.stream().filter(NumberUtil::notNullAndPositive).distinct().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(filterCartIds)) {
            return;
        }

        searchFeignService.emptyProductCartAsync(shopType, filterCartIds);
    }

    /**
     * 当订单完成后要执行的操作
     *
     * @param order 订单
     */
    @Override
    public void operateAfterOrderAccomplished(OrderDO order) {
        if(!order.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) || !order.getVendorInnerStatus().equals(VendorInnerStatusEnum.ACCOMPLISHED.getCode()) || !order.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) {
            return;
        }

        //通知会员服务，计算会员权益积分
        //积分商品不能享受积分权益
        Integer orderType = order.getOrderType();
        if(!orderType.equals(OrderTypeEnum.CREDITS_EXCHANGE.getCode()) && !orderType.equals(OrderTypeEnum.CHANNEL_POINT_EXCHANGE.getCode())){
            memberFeignService.calculateMemberLrcAsync(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getVendorMemberId(), order.getVendorRoleId(), order.getTotalAmount(), order.getOrderNo());
        }

        //通知会员服务，记录订单，待评论订单
        memberFeignService.saveMemberOrderCommentAsync(order);

        //Srm订单和采购请购单不需要交易记录、不需要更新成交数量
        if(!(order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || OrderSourceKindEnum.REQUISITION.getCode().equals(order.getOrderKind()))) {
            //记录商品交易记录
            baseOrderHistoryService.saveOrderProductHistory(order);

            //通知商品服务，更新商品成交数量
            productFeignService.updateProductSoldCountAsync(order.getShopId(), order.getShopType(), order.getBuyerMemberId(), order.getBuyerRoleId(), order.getBuyerMemberName(), order.getProducts().stream().map(p -> new OrderProductStockDTO(p.getSkuId(), p.getStockId(), p.getQuantity())).collect(Collectors.toList()));
        }

        //如果订单类型是 采购询价合同、采购竞价合同、采购招标合同、请购单采购
        //通知商品服务, 进行物料价格信息更新
        if (orderType.equals(OrderTypeEnum.QUERY_PRICE_CONTRACT.getCode()) || orderType.equals(OrderTypeEnum.PRICE_COMPETITION_CONTRACT_PURCHASE.getCode()) || orderType.equals(OrderTypeEnum.PURCHASE_CONTRACT_BIDDING.getCode()) || orderType.equals(OrderTypeEnum.REQUISITION_TO_PURCHASE.getCode())){
            List<MaterielPriceRequest> materielPrices = order.getProducts().stream().map(orderProductDO -> {
                MaterielPriceRequest materielPriceRequest = new MaterielPriceRequest();
                materielPriceRequest.setCode(orderProductDO.getProductNo());
                materielPriceRequest.setAmount(orderProductDO.getPrice().doubleValue());
                return materielPriceRequest;
            }).collect(Collectors.toList());
            OrderPriceRequest request=new OrderPriceRequest();
            request.setContractNo(order.getOrderNo());
            request.setStartTime(order.getCreateTime() != null ? order.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() : null);
            request.setEndTime(order.getCreateTime() != null ? order.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() : null);
            request.setPartyAMemberId(order.getBuyerMemberId());
            request.setPartyARoleId(order.getBuyerRoleId());
            request.setPartyAName(order.getBuyerMemberName());
            request.setPartyBMemberId(order.getVendorMemberId());
            request.setPartyBRoleId(order.getVendorRoleId());
            request.setPartyBName(order.getVendorMemberName());
            request.setMaterielPrices(materielPrices);
            String json = JSONUtil.toJsonStr(request);
            try {
                logger.info("物料价格信息更新任务推送至消息队列 => " + json);
                rabbitTemplate.convertAndSend(OrderServiceContants.ORDER_GOODS_PRICE_CHANGE_EXCHANGE, OrderServiceContants.ORDER_GOODS_PRICE_CHANGE_ROUTING_KEY, json);
            } catch (Exception e) {
                logger.error("物料价格信息更新任务推送至延迟消息队列错误，data: " + json + ", error:" + e.getMessage());
            }
        }

    }

    /**
     * 订单创建（提交）完成后，向报表服务发送供应商订单金额
     *
     * @param order 订单
     */
    @Override
    public void reportVendorOrderAmount(OrderDO order) {
        reportFeignService.reportVendorOrderAmountAsync(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getVendorMemberId(), order.getVendorRoleId(), order.getTotalAmount().doubleValue());
    }

    /**
     * 订单批量创建（提交）完成后，向报表服务发送供应商订单金额
     *
     * @param orders 订单列表
     */
    @Override
    public void reportVendorOrderAmount(List<OrderDO> orders) {
        orders.stream().collect(Collectors.groupingBy(order -> new MemberDTO(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getVendorMemberId(), order.getVendorRoleId(), ""), Collectors.summingDouble(order -> order.getTotalAmount().doubleValue())))
                .forEach((key, value) -> reportFeignService.reportVendorOrderAmountAsync(key.getBuyerMemberId(), key.getBuyerRoleId(), key.getMemberId(), key.getRoleId(), value));
    }

    /**
     * 向报表服务发送采购商订单统计数据
     *
     * @param buyerMemberId           采购会员Id
     * @param buyerRoleId             采购会员角色Id
     * @param lastBuyerInnerStatus    （流程执行之前的、上一次的采购商内部状态）对应要减少统计的操作，如为0或Null表示不减少
     * @param currentBuyerInnerStatus （流程执行之后的，当前的采购商内部张贴）对应要增加统计的操作，如为0或Null表示不增加
     */
    @Override
    public void reportBuyerOrder(Long buyerMemberId, Long buyerRoleId, Integer lastBuyerInnerStatus, Integer currentBuyerInnerStatus) {
        reportBuyerOrder(buyerMemberId, buyerRoleId, BuyerInnerStatusEnum.parse(lastBuyerInnerStatus), 1, BuyerInnerStatusEnum.parse(currentBuyerInnerStatus), 1);
    }

    /**
     * 向消息服务发送采购商订单消息
     *
     * @param buyerMemberId           采购会员Id
     * @param buyerRoleId             采购会员角色Id
     * @param currentBuyerInnerStatus （流程执行之后的）当前的采购商内部状态
     * @param orderNo                 订单号
     * @param digest                  订单摘要
     */
    @Override
    public void messageBuyerOrder(Long buyerMemberId, Long buyerRoleId, Long userId, Integer currentBuyerInnerStatus, String orderNo, String digest) {
        String messageCode = BuyerInnerStatusEnum.getMessageCode(currentBuyerInnerStatus);
        if(StringUtils.hasLength(messageCode)) {
            messageFeignService.sendOrderMessageAsync(buyerMemberId, buyerRoleId,userId, messageCode, orderNo, digest);
        }
    }

    /**
     * 向消息服务发送采购商订单收货确认消息（含自提商品）
     * @param buyerMemberId 采购会员Id
     * @param buyerRoleId   采购会员角色Id
     * @param messageCode   消息模板code
     * @param orderNo       订单号
     * @param digest        订单摘要
     * @param address       自提地址
     * @param selfCode      自提码
     */
    @Override
    public void messageBuyerDeliverSelfOrder(Long buyerMemberId, Long buyerRoleId, Long userId, String messageCode, String orderNo, String digest, String address, String selfCode) {
        messageFeignService.sendOrderMessageAsync(buyerMemberId, buyerRoleId, userId,messageCode, Arrays.asList(orderNo, digest, address, selfCode));
    }

    /**
     * 向消息服务发送采购商订单收货确认消息（不含自提商品）
     * @param buyerMemberId 采购会员Id
     * @param buyerRoleId   采购会员角色Id
     * @param messageCode   消息模板code
     * @param orderNo       订单号
     * @param digest        订单摘要
     * @param company       物流公司
     * @param logisticsNo   物流单号
     */
    @Override
    public void messageBuyerDeliverOrder(Long buyerMemberId, Long buyerRoleId, Long userId, String messageCode, String orderNo, String digest, String company, String logisticsNo) {
        messageFeignService.sendOrderMessageAsync(buyerMemberId, buyerRoleId, userId,messageCode, Arrays.asList(orderNo, digest, company, logisticsNo));
    }

    /**
     * 向报表服务发送采购商订单统计数据
     *
     * @param buyerMemberId               采购会员Id
     * @param buyerRoleId                 采购会员角色Id
     * @param lastBuyerInnerStatusEnum    （流程执行之前的、上一次的采购商内部状态）对应要减少统计的操作，如为0或Null表示不减少
     * @param currentBuyerInnerStatusEnum （流程执行之后的，当前的采购商内部张贴）对应要增加统计的操作，如为0或Null表示不增加
     */
    @Override
    public void reportBuyerOrder(Long buyerMemberId, Long buyerRoleId, BuyerInnerStatusEnum lastBuyerInnerStatusEnum, BuyerInnerStatusEnum currentBuyerInnerStatusEnum) {
        reportBuyerOrder(buyerMemberId, buyerRoleId, lastBuyerInnerStatusEnum, 1, currentBuyerInnerStatusEnum, 1);
    }

    /**
     * 向消息服务发送供应商订单消息
     *
     * @param vendorMemberId           供应会员Id
     * @param vendorRoleId             供应会员角色Id
     * @param currentVendorInnerStatus （流程执行之后的）当前的供应商内部状态
     * @param orderNo                  订单号
     * @param digest                   订单摘要
     */
    @Override
    public void messageVendorOrder(Long vendorMemberId, Long vendorRoleId, Long userId, Integer currentVendorInnerStatus, String orderNo, String digest) {
        String messageCode = VendorInnerStatusEnum.getMessageCode(currentVendorInnerStatus);
        if(StringUtils.hasLength(messageCode)) {
            messageFeignService.sendOrderMessageAsync(vendorMemberId, vendorRoleId,userId, messageCode, orderNo, digest);
        }
    }

    /**
     * （批量）向报表服务发送采购商订单统计数据
     *
     * @param buyerMemberId               采购会员Id
     * @param buyerRoleId                 采购会员角色Id
     * @param lastBuyerInnerStatusEnum    （流程执行之前的、上一次的采购商内部状态）对应要减少统计的操作，如为0或Null表示不减少
     * @param decreaseCount               增加的数量
     * @param currentBuyerInnerStatusEnum （流程执行之后的，当前的采购商内部张贴）对应要增加统计的操作，如为0或Null表示不增加
     * @param increaseCount               减少的数量
     */
    @Override
    public void reportBuyerOrder(Long buyerMemberId, Long buyerRoleId, BuyerInnerStatusEnum lastBuyerInnerStatusEnum, int decreaseCount, BuyerInnerStatusEnum currentBuyerInnerStatusEnum, int increaseCount) {
        Integer decreaseBuyerOperateCode = lastBuyerInnerStatusEnum == null ? 0 : lastBuyerInnerStatusEnum.getReportTypeCode();
        Integer increaseBuyerOperateCode = currentBuyerInnerStatusEnum == null ? 0 : currentBuyerInnerStatusEnum.getReportTypeCode();
        if(decreaseBuyerOperateCode.equals(0) && increaseBuyerOperateCode.equals(0)) {
            return;
        }

        reportFeignService.reportBuyerOrderAsync(buyerMemberId, buyerRoleId, decreaseBuyerOperateCode, (long) decreaseCount, increaseBuyerOperateCode, (long) increaseCount);
    }

    /**
     * 向报表服务发送供应商订单统计数据
     *
     * @param vendorMemberId           供应会员Id
     * @param vendorRoleId             供应会员角色Id
     * @param lastVendorInnerStatus    （流程执行之前的、上一次的供应商内部状态）对应要减少统计的操作，如为0或Null表示不减少
     * @param currentVendorInnerStatus （流程执行之后的，当前的供应商内部张贴）对应要增加统计的操作，如为0或Null表示不增加
     */
    @Override
    public void reportVendorOrder(Long vendorMemberId, Long vendorRoleId, Integer lastVendorInnerStatus, Integer currentVendorInnerStatus) {
        Integer decreaseVendorOperateCode = lastVendorInnerStatus == null ? 0 : VendorInnerStatusEnum.getReportCode(lastVendorInnerStatus);
        Integer increaseVendorOperateCode = currentVendorInnerStatus == null ? 0 : VendorInnerStatusEnum.getReportCode(currentVendorInnerStatus);
        if(decreaseVendorOperateCode.equals(0) && increaseVendorOperateCode.equals(0)) {
            return;
        }

        reportFeignService.reportVendorOrderAsync(vendorMemberId, vendorRoleId, decreaseVendorOperateCode, increaseVendorOperateCode);
    }

    /**
     * 向报表服务发送供应商订单统计数据
     *
     * @param vendorMemberId               供应会员Id
     * @param vendorRoleId                 供应会员角色Id
     * @param lastVendorInnerStatusEnum    （流程执行之前的、上一次的供应商内部状态）对应要减少统计的操作，如为0或Null表示不减少
     * @param currentVendorInnerStatusEnum （流程执行之后的，当前的供应商内部张贴）对应要增加统计的操作，如为0或Null表示不增加
     */
    @Override
    public void reportVendorOrder(Long vendorMemberId, Long vendorRoleId, VendorInnerStatusEnum lastVendorInnerStatusEnum, VendorInnerStatusEnum currentVendorInnerStatusEnum) {
        Integer decreaseVendorOperateCode = lastVendorInnerStatusEnum == null ? 0 : lastVendorInnerStatusEnum.getReportTypeCode();
        Integer increaseVendorOperateCode = currentVendorInnerStatusEnum == null ? 0 : currentVendorInnerStatusEnum.getReportTypeCode();
        if(decreaseVendorOperateCode.equals(0) && increaseVendorOperateCode.equals(0)) {
            return;
        }

        reportFeignService.reportVendorOrderAsync(vendorMemberId, vendorRoleId, decreaseVendorOperateCode, increaseVendorOperateCode);
    }

    /**
     * （批量）向报表服务发送供应商订单统计数据
     *
     * @param orders 订单列表
     * @param currentVendorInnerStatusEnum 当前的供应商内部状态
     */
    @Override
    public void reportVendorOrder(List<OrderDO> orders, VendorInnerStatusEnum currentVendorInnerStatusEnum) {
        orders.stream().collect(Collectors.groupingBy(order -> new MemberDTO(order.getVendorMemberId(), order.getVendorRoleId(), ""), Collectors.counting()))
                .forEach((key, value) -> reportFeignService.reportVendorOrderAsync(key.getMemberId(), key.getRoleId(), null, 0L, currentVendorInnerStatusEnum.getReportTypeCode(), value));
    }

    /**
     * 当拼团订单处于“待发货”状态时，向营销服务发送数据
     *
     * @param order 订单
     */
    @Override
    public void notifyGroupOrder(OrderDO order) {
        //拼团订单要处于“待发货”状态才通知营销服务
        if(!order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) || !order.getOuterStatus().equals(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode())) {
            return;
        }

        //如果已经通知过了，不再通知
        if(order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode()) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_FAILED.getCode()) || order.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_SUCCESS.getCode())) {
            return;
        }

        AtomicReference<Long> productId = new AtomicReference<>(0L);
        AtomicReference<Long> skuId = new AtomicReference<>(0L);
        AtomicReference<Long> promotionId = new AtomicReference<>(0L);
        AtomicReference<Long> recordId = new AtomicReference<>(0L);
        AtomicReference<Integer> belongType = new AtomicReference<>(0);
        AtomicReference<BigDecimal> quantity = new AtomicReference<>(BigDecimal.ZERO);

        order.getProducts().stream().findFirst().ifPresent(product -> {
            productId.set(product.getProductId());
            skuId.set(product.getSkuId());
            quantity.set(product.getQuantity());
            product.getPromotions().stream().findFirst().ifPresent(promotion -> {
                promotionId.set(promotion.getPromotionId());
                recordId.set(promotion.getRecordId());
                belongType.set(promotion.getBelongType());
            });
        });

        //修改订单营销活动状态，在外部要保存订单
        order.setPromotionStatus(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode());
        // 查询采购商会员Logo
        String buyerMemberLogo = findVendorMemberLogo(order.getBuyerMemberId());

        //通知营销服务，获得拼团Id
        Wrapper<Long> groupResult = marketingFeignService.notifyGroupOrder(order.getId(), order.getOrderNo(), order.getBuyerMemberId(), order.getBuyerRoleId(), order.getBuyerMemberName(), buyerMemberLogo, productId.get(), skuId.get(), quantity.get(), promotionId.get(), recordId.get(), belongType.get());
        if(groupResult.getCode() == ResponseCode.SUCCESS.getCode()) {
            order.setGroupId(groupResult.getData());
        }

        orderRepository.saveAndFlush(order);

        //如果拼团失败，重新加入队列，待消费者进行退款处理
        if(groupResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    baseOrderScheduleService.scheduleGroupOrder(order.getId(), groupResult.getData());
                }
            });
        }
    }

    /**
     * 当订单外部状态是代发货时,发放优惠券,并发送通知消息
     * @param order 订单
     */
    @Override
    public void sendCoupons(OrderDO order){
        //订单不是SRM订单才发放优惠券
        if(order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode())) {
            return;
        }
        //订单要处于“待发货”状态才发放优惠券
        if(!order.getOuterStatus().equals(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode())) {
            return;
        }
        Set<OrderGiveCouponDO> giveCoupons = order.getGiveCoupons();
        GiftCouponRequest giftCouponRequest = new GiftCouponRequest();
        List<GiftCouponItemRequest> list = new ArrayList();
        giftCouponRequest.setMemberId(order.getBuyerMemberId());
        giftCouponRequest.setRoleId(order.getBuyerRoleId());
        giftCouponRequest.setShopId(order.getShopId());
        giftCouponRequest.setMemberName(order.getBuyerMemberName());
        if(!CollectionUtils.isEmpty(giveCoupons)){
            for (OrderGiveCouponDO giveCoupon : giveCoupons) {
                GiftCouponItemRequest giftCouponItemRequest = new GiftCouponItemRequest();
                giftCouponItemRequest.setOrderNo(order.getOrderNo());
                giftCouponItemRequest.setBelongType(2);
                giftCouponItemRequest.setCouponId(giveCoupon.getGiveId());
                BigDecimal quantity = giveCoupon.getQuantity();
                giftCouponItemRequest.setQuantity(quantity == null? 0:quantity.intValue());
                list.add(giftCouponItemRequest);
            }
        }

        giftCouponRequest.setCouponList(list);
        String jsonMessage = JSONUtil.toJsonStr(giftCouponRequest);
        //发送到mq队列
        baseOrderScheduleService.sengCoupon(jsonMessage);
        //给采购商发送通知消息
        messageFeignService.sendOrderMessageAsync(order.getBuyerMemberId(),order.getBuyerRoleId(),order.getBuyerUserId(), MessageTemplateCode.marketing_gift_coupon,order.getOrderNo(),order.getDigest());
    }

    /**
     * 向合同服务发送SRM订单数据
     *
     * @param order 订单
     */
    @Override
    public void sendSrmOrder(OrderDO order) {
        if(!order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || order.getContract() == null || CollectionUtils.isEmpty(order.getProducts())) {
            return;
        }

        contractFeignService.createSrmOrderAsync(order.getId(), order.getTotalAmount(), order.getContract().getContractId(), order.getProducts().stream().map(orderProduct -> {
            OrderProductDTO product = new OrderProductDTO();
            product.setProductId(orderProduct.getProductId());
            product.setProductNo(orderProduct.getProductNo());
            product.setQuantity(orderProduct.getQuantity());
            return product;
        }).collect(Collectors.toList()));
    }

    /**
     * 批量向合同服务发送SRM订单数据
     *
     * @param orders 订单列表
     */
    @Override
    public void batchSendSrmOrder(List<OrderDO> orders) {
        orders.stream().filter(order -> order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) && order.getContract() != null && !CollectionUtils.isEmpty(order.getProducts())).forEach(order -> contractFeignService.createSrmOrderAsync(order.getId(), order.getTotalAmount(), order.getContract().getContractId(), order.getProducts().stream().map(orderProduct -> {
            OrderProductDTO product = new OrderProductDTO();
            product.setProductId(orderProduct.getProductId());
            product.setProductNo(orderProduct.getProductNo());
            product.setQuantity(orderProduct.getQuantity());
            return product;
        }).collect(Collectors.toList())));
    }

    /**
     * 向合同服务取消SRM订单数据
     *
     * @param order 订单
     */
    @Override
    public void cancelSrmOrder(OrderDO order) {
        if(!order.getOrderKind().equals(OrderSourceKindEnum.SRM.getCode()) || order.getContract() == null || CollectionUtils.isEmpty(order.getProducts())) {
            return;
        }

        contractFeignService.cancelSrmOrderAsync(order.getId(), order.getTotalAmount(), order.getContract().getContractId(), order.getProducts().stream().map(orderProduct -> {
            OrderProductDTO product = new OrderProductDTO();
            product.setProductId(orderProduct.getProductId());
            product.setProductNo(orderProduct.getProductNo());
            product.setQuantity(orderProduct.getQuantity());
            return product;
        }).collect(Collectors.toList()));
    }

    /**
     * 查询供应商店铺或商城Logo
     *
     * @param shopId  商城Id
     * @param vendors 供应商列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<VendorLogoDTO>> checkVendorShopLogos(Long shopId, List<VendorBO> vendors) {
        return platformTemplateFeignService.findVendorShopLogos(shopId, vendors);
    }

    /**
     * 查询供应商店铺或商城Logo
     *
     * @param shopId         商城Id
     * @param vendorMemberId 供应商会员Id
     * @param vendorRoleId   供应商会员角色Id
     * @return 供应商Logo
     */
    @Override
    public Wrapper<VendorLogoDTO> checkVendorShopLogo(Long shopId, Long vendorMemberId, Long vendorRoleId) {
        return platformTemplateFeignService.findVendorShopLogo(shopId, vendorMemberId, vendorRoleId);
    }

    /**
     * 查询供应商店铺或商城Logo
     *
     * @param shopId  商城Id
     * @param vendors 供应商列表
     * @return 查询结果
     */
    @Override
    public List<VendorLogoDTO> findVendorShopLogos(Long shopId, List<VendorBO> vendors) {
        Wrapper<List<VendorLogoDTO>> logoResult = platformTemplateFeignService.findVendorShopLogos(shopId, vendors);
        return logoResult.getCode() == ResponseCode.SUCCESS.getCode() && !CollectionUtils.isEmpty(logoResult.getData()) ? logoResult.getData() : new ArrayList<>();
    }

    /**
     * 查询供应商店铺或商城Logo
     *
     * @param shopId         商城Id
     * @param vendorMemberId 供应商会员Id
     * @param vendorRoleId   供应商会员角色Id
     * @return 供应商Logo
     */
    @Override
    public String findVendorShopLogo(Long shopId, Long vendorMemberId, Long vendorRoleId) {
        Wrapper<VendorLogoDTO> logoResult = platformTemplateFeignService.findVendorShopLogo(shopId, vendorMemberId, vendorRoleId);
        return logoResult.getCode() == ResponseCode.SUCCESS.getCode() && Objects.nonNull(logoResult.getData()) ? logoResult.getData().getLogo() : "";
    }

    /**
     * 批量查询供应商店铺或商城Logo
     *
     * @param vendorShopMap 要转单的订单
     * @return 供应商店铺或商城Logo
     */
    @Override
    public List<VendorLogoDTO> batchFindVendorShopLogos(Map<Long, List<VendorBO>> vendorShopMap) {
        if(CollectionUtils.isEmpty(vendorShopMap)) {
            return new ArrayList<>();
        }

        List<VendorLogoDTO> vendorLogos = new ArrayList<>();
        for (Map.Entry<Long, List<VendorBO>> entry : vendorShopMap.entrySet()) {
            Wrapper<List<VendorLogoDTO>> logoResult = platformTemplateFeignService.findVendorShopLogos(entry.getKey(), entry.getValue());
            if(logoResult.getCode() == ResponseCode.SUCCESS.getCode() && !CollectionUtils.isEmpty(logoResult.getData())) {
                vendorLogos.addAll(logoResult.getData());
            }
        }

        return vendorLogos;
    }


    /**
     * 查询供应商会员Logo
     *
     * @param vendorMemberId 供应商会员Id
     * @return 供应商会员Logo
     */
    @Override
    public String findVendorMemberLogo(Long vendorMemberId) {
        Wrapper<MemberLogoDTO> logoResult = memberFeignService.findMemberLogo(vendorMemberId);
        return logoResult.getCode() == ResponseCode.SUCCESS.getCode() && Objects.nonNull(logoResult.getData()) ? logoResult.getData().getLogo() : "";
    }

    /**
     * 订单创建完成后，通知营销服务，扣减营销活动记录、优惠券使用记录
     *
     * @param orders 订单列表
     */
    @Override
    public void notifyPromotions(List<OrderDO> orders) {
        for (OrderDO order : orders) {
            //扣减营销活动记录
            List<PromotionNotifyDTO> notifyList = order.getProducts().stream().filter(product -> !CollectionUtils.isEmpty(product.getPromotions())).map(product -> {
                PromotionNotifyDTO notify = new PromotionNotifyDTO();
                notify.setSkuId(product.getSkuId());
                notify.setOrderNo(order.getOrderNo());
                notify.setRefPrice(product.getRefPrice());
                notify.setQuantity(product.getQuantity());
                notify.setPromotions(product.getPromotions().stream().map(productPromotion -> {
                    PromotionDTO promotion = new PromotionDTO();
                    promotion.setPromotionId(productPromotion.getPromotionId());
                    promotion.setBelongType(productPromotion.getBelongType());
                    return promotion;
                }).collect(Collectors.toList()));
                return notify;
            }).collect(Collectors.toList());

            if(!CollectionUtils.isEmpty(notifyList)) {
                marketingFeignService.updateOrderPromotions(order.getId(), order.getCreateTime(), order.getBuyerMemberId(), order.getBuyerRoleId(), order.getBuyerMemberName(), order.getShopId(), order.getShopName(), notifyList);
            }

            //扣减优惠券记录
            List<OrderCouponDetailDTO> coupons = order.getCoupons().stream().map(coupon -> {
                OrderCouponDetailDTO detail = new OrderCouponDetailDTO();
                detail.setCouponId(coupon.getCouponId());
                detail.setBelongType(coupon.getBelongType());
                return detail;
            }).collect(Collectors.toList());

            if(!CollectionUtils.isEmpty(coupons)) {
                marketingFeignService.spendCoupons(order.getShopId(), order.getShopName(), order.getId(), order.getOrderNo(), order.getBuyerMemberId(), order.getBuyerRoleId(), order.getBuyerMemberName(), order.getCreateTime(), order.getTotalAmount(), coupons);
            }
        }
    }

    /**
     * 订单取消后，通知营销服务，返还营销活动、优惠券记录
     *
     * @param order 订单
     */
    @Override
    public void resumePromotions(OrderDO order) {
        //返还营销记录（这里要将商品的购买数量设置为负数）
        List<PromotionNotifyDTO> notifyList = order.getProducts().stream().filter(product -> !CollectionUtils.isEmpty(product.getPromotions())).map(product -> {
            PromotionNotifyDTO notify = new PromotionNotifyDTO();
            notify.setSkuId(product.getSkuId());
            notify.setOrderNo(order.getOrderNo());
            notify.setRefPrice(product.getRefPrice());
            notify.setQuantity(product.getQuantity().multiply(BigDecimal.valueOf(-1)));
            notify.setPromotions(product.getPromotions().stream().map(productPromotion -> {
                PromotionDTO promotion = new PromotionDTO();
                promotion.setPromotionId(productPromotion.getPromotionId());
                promotion.setBelongType(productPromotion.getBelongType());
                return promotion;
            }).collect(Collectors.toList()));
            return notify;
        }).collect(Collectors.toList());

        if(!CollectionUtils.isEmpty(notifyList)) {
            marketingFeignService.updateOrderPromotions(order.getId(), order.getCreateTime(), order.getBuyerMemberId(), order.getBuyerRoleId(), order.getBuyerMemberName(), order.getShopId(), order.getShopName(), notifyList);
        }

        //返还优惠券记录
        List<OrderCouponDetailDTO> coupons = order.getCoupons().stream().map(coupon -> {
            OrderCouponDetailDTO detail = new OrderCouponDetailDTO();
            detail.setCouponId(coupon.getCouponId());
            detail.setBelongType(coupon.getBelongType());
            return detail;
        }).collect(Collectors.toList());

        if(!CollectionUtils.isEmpty(coupons)) {
            marketingFeignService.resumeCoupons(coupons);
        }
    }

    /**
     * 订单支付后，将“平台优惠券”同步给结算服务
     *
     * @param orders 订单列表
     */
    @Override
    public void notifyPlatformCoupons(List<OrderDO> orders) {
        //如果订单没有“平台优惠券”，则不用发送
        orders.forEach(order -> settleAccountFeignService.notifyOrderCouponSettlement(order.getVendorMemberId(), order.getVendorRoleId(), order.getVendorMemberName(), order.getCreateTime(), order.getSubmitTime(), order.getOrderType(), order.getOrderNo(), order.getDigest(), order.getTotalAmount(), order.getCoupons().stream().filter(coupon -> coupon.getBelongType().equals(BelongTypeEnum.PLATFORM.getCode())).collect(Collectors.toMap(OrderCouponDO::getCouponId, OrderCouponDO::getAmount))));
    }

    /**
     * 生成小程序码
     * @param params 二维码参数
     * @param page   跳转页面路径
     * @return base64编码
     */
    @Override
    public Wrapper<String> createMiniCode(String params, String page) {
        //获取小程序配置参数
        PlatformPaymentParameterDO parameterDO = platformPaymentParameterRepository.findFirstByPayTypeAndPayChannel(OrderPayTypeEnum.ONLINE_PAYMENT.getCode(), OrderPayChannelEnum.WECHAT_PAY.getCode());
        if (parameterDO == null) {
            return Wrapper.fail(ResponseCode.WECHAT_MINI_APP_ID_SECRET_MISSING);
        }
        //小程序ID、秘钥
        String appId = parameterDO.getParameters().stream().filter(param -> OrderPaymentParameterEnum.WECHAT_APPLET_APP_ID.getCode().equals(param.getCode())).map(PaymentParameterBO::getValue).findFirst().orElse(null);
        String appSecret = parameterDO.getParameters().stream().filter(param -> OrderPaymentParameterEnum.WECHAT_APPLET_APP_KEY.getCode().equals(param.getCode())).map(PaymentParameterBO::getValue).findFirst().orElse(null);
        if (appId == null || appSecret == null) {
            return Wrapper.fail(ResponseCode.WECHAT_MINI_APP_ID_SECRET_MISSING);
        }
        try {
            return Wrapper.success(QRCodeUtil.createMiniAppCode(appId, appSecret, params, page));
        } catch (WxErrorException e) {
            e.printStackTrace();
            return Wrapper.fail(e.getMessage());
        }
    }

    /**
     * 分页查询订单转单列表
     * @param memberId              供应商会员id
     * @param memberRoleId          角色id
     * @param orderNo               订单号
     * @param digest                订单摘要
     * @param buyerMemberName       采购会员名称
     * @param startDate             下单开始时间
     * @param endDate               下单结束时间
     * @param orderTransitionType   转单状态
     * @param current               当前页
     * @param pageSize              每页数量
     * @return
     */
    @Override
    public Page<OrderDO> pageTransitionOrderList(Long memberId, Long memberRoleId, String orderNo, String digest, String buyerMemberName, String startDate, String endDate, Integer orderTransitionType, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current -1, pageSize, Sort.by("id").descending());
        Specification<OrderDO> specification = (Specification<OrderDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            //下单模式(进货单下单或询价报价下单)
            List<Integer> orderModeList = new ArrayList<>();
            //订单外部状态(不等于已完成/已取消/已中止/不接受订单/不同意签订电子合同)
            List<Integer> orderOutStatusList = new ArrayList<>();
            orderModeList.add(OrderModeEnum.BUYER.getCode());
            orderModeList.add(OrderModeEnum.QUOTATION.getCode());
            orderOutStatusList.add(OrderOuterStatusEnum.ACCOMPLISHED.getCode());
            orderOutStatusList.add(OrderOuterStatusEnum.CANCELLED.getCode());
            orderOutStatusList.add(OrderOuterStatusEnum.TERMINATED.getCode());
            orderOutStatusList.add(OrderOuterStatusEnum.NOT_ACCEPT.getCode());
            orderOutStatusList.add(OrderOuterStatusEnum.NOT_ACCEPT_CONTRACT.getCode());
            //供应商会员id
            list.add(criteriaBuilder.equal(root.get("vendorMemberId").as(Long.class), memberId));
            //供应商角色id
            list.add(criteriaBuilder.equal(root.get("vendorRoleId").as(Long.class), memberRoleId));
            //订单商品的上游供应会员不为空
            list.add(criteriaBuilder.notEqual(root.get("supplyMemberId").as(Long.class),0L));
            //订单下单模式=进货单下单或询价报价下单
            list.add(criteriaBuilder.in(root.get("orderMode")).value(orderModeList));
            //订单外部状态不等于已完成/已取消/已中止/不接受订单/不同意签订电子合同且订单未发过货
            list.add(criteriaBuilder.not(criteriaBuilder.in(root.get("orderOutStatus")).value(orderOutStatusList)));
            list.add(criteriaBuilder.equal(root.get("vendorRoleId").as(Long.class), memberRoleId));
            //订单未发过货
            list.add(criteriaBuilder.equal(root.get("hasDelivered").as(Boolean.class),Boolean.FALSE));
            //订单转单状态为待转单
//            list.add(criteriaBuilder.equal(root.get("transitionStatus").as(Integer.class),OrderTransitionStatusEnum.WAIT.getCode()));
            //订单编号
            if(StringUtils.hasLength(orderNo)) {
                list.add(criteriaBuilder.like(root.get("orderNo").as(String.class), "%" + orderNo.trim() + "%"));
            }

            //订单摘要
            if(StringUtils.hasLength(digest)) {
                list.add(criteriaBuilder.like(root.get("digest").as(String.class), "%" + digest.trim() + "%"));
            }

            //供应会员名称
            if(StringUtils.hasLength(buyerMemberName)) {
                list.add(criteriaBuilder.like(root.get("buyerMemberName").as(String.class), "%" + buyerMemberName.trim() + "%"));
            }

            //订单起始时间
            if (StringUtils.hasLength(startDate)) {
                list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(startDate.concat(" 00:00:00"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单结束时间
            if (StringUtils.hasLength(endDate)) {
                list.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), LocalDateTime.parse(endDate.concat(" 23:59:59"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))));
            }

            //订单类型
            if(NumberUtil.notNullOrZero(orderTransitionType)) {
                list.add(criteriaBuilder.equal(root.get("orderTransitionType").as(Integer.class), orderTransitionType));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return orderRepository.findAll(specification, pageable);
    }
}
